home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / printing / magicfil.2 / magicfilter-1.2.tar / magicfilter-1.2 / parseconfig.c < prev    next >
C/C++ Source or Header  |  1995-04-15  |  9KB  |  429 lines

  1. /*
  2.  * parseconfig.c
  3.  * 
  4.  * Routine library for parsing the configuration file
  5.  *
  6.  * Copyright ⌐ 1995 H. Peter Anvin
  7.  */
  8.  
  9. #include "magicfilter.h"
  10.  
  11. /*
  12.  * int getoffset(char *startpos, char **endpos)
  13.  *
  14.  * Returns the parsing offset (a decimal, octal or hex number, or "default").
  15.  * Returns the number, or one of the negative numbers
  16.  *    MAG_DEFAULT      ... is default
  17.  *    MAG_COMMENT      ... comment line
  18.  *    MAG_ERR          ... invalid offset
  19.  *
  20.  * *endpos is set to the first character after the offset, unless NULL
  21.  */
  22.  
  23. int getoffset(char *p, char **endpos)
  24. {
  25.   int offset = 0;        /* So far */
  26.   enum { st_start, st_zero, st_oct, st_dec, st_hex, st_done } state = st_start;
  27.  
  28. #if DEBUG > 3
  29.   fprintf(stderr,"getoffset %s\n", p);
  30. #endif
  31.  
  32.   while ( isspace(*p) ) p++;    /* Skip leading whitespace */
  33.  
  34.   while ( state != st_done )
  35.     {
  36.       switch( state )
  37.     {
  38.     case st_start:
  39.       switch ( *p )
  40.         {
  41.         case '\b':        /* Whitespace */
  42.         case '\t':
  43.         case '\n':
  44.         case '\v':
  45.         case '\f':
  46.         case '\r':
  47.         case ' ':
  48.           p++;
  49.           break;
  50.           
  51.         case '#':
  52.         case '\0':        /* Blank line counts as comment */
  53.           offset = MAG_COMMENT;
  54.           state = st_done;
  55.           break;
  56.  
  57.         case '0':
  58.           state = st_zero;
  59.           p++;
  60.           break;
  61.  
  62.         case '1':
  63.         case '2':
  64.         case '3':
  65.         case '4':
  66.         case '5':
  67.         case '6':
  68.         case '7':
  69.         case '8':
  70.         case '9':
  71.           offset = *p - '0';
  72.           state = st_dec;
  73.           p++;
  74.           break;
  75.           
  76.         case 'd':
  77.           if ( strncmp(p, "default", 7) )
  78.         {
  79.           offset = MAG_ERR;
  80.         }
  81.           else
  82.         {
  83.           p += 7;
  84.           offset = MAG_DEFAULT;
  85.         }
  86.           state = st_done;
  87.           break;
  88.  
  89.         default:
  90.           offset = MAG_ERR;
  91.           state = st_done;
  92.           break;
  93.         }
  94.       break;
  95.  
  96.     case st_zero:
  97.       if ( *p == 'x' || *p == 'X' )
  98.         {
  99.           state = st_hex;
  100.           p++;
  101.           break;
  102.         }
  103.       /* else fall through */
  104.  
  105.     case st_oct:
  106.       if ( *p < '0' || *p > '7' )
  107.         {
  108.           state = st_done;
  109.         }
  110.       else
  111.         {
  112.           offset <<= 3;
  113.           offset += *(p++) - '0';
  114.         }
  115.       break;
  116.  
  117.     case st_dec:
  118.       if ( *p < '0' || *p > '9' )
  119.         {
  120.           state = st_done;
  121.         }
  122.       else
  123.         {
  124.           offset *= 10;
  125.           offset += *(p++) - '0';
  126.         }
  127.       break;
  128.  
  129.     case st_hex:
  130.       if ( *p >= '0' && *p <= '9' )
  131.         {
  132.           offset <<= 4;
  133.           offset += *(p++) - '0';
  134.         }
  135.       else if ( *p >= 'A' && *p <= 'F' )
  136.         {
  137.           offset <<= 4;
  138.           offset += *(p++) - 'A' + 10;
  139.         }
  140.       else if ( *p >= 'a' && *p <= 'f' )
  141.         {
  142.           offset <<= 4;
  143.           offset += *(p++) - 'a' + 10;
  144.         }
  145.       else
  146.         {
  147.           state = st_done;
  148.         }
  149.     }
  150.     }
  151.  
  152.   if ( endpos )
  153.     *endpos = p;        /* Where did we end? */
  154.  
  155.   return offset;
  156. }
  157.  
  158. /*
  159.  * int getmagic(char *startpos, char **endpos, char *magic, char *mask)
  160.  *
  161.  * Parse a magic string, returning the number of bytes in the magic string.
  162.  * Stores the endpoint in *endpos if requested.  If magic and/or mask
  163.  * is NULL, do not store; used to count the number of characters in the
  164.  * magic/mask string.
  165.  *
  166.  * Each character in mask is either 0 for \? (don't care) or (char)-1 for
  167.  * any other (do care).
  168.  *
  169.  * If mask is set to the senitel value NO_WILD (a unique pointer value
  170.  * pointing to a bogus static string) the \? will not be interpreted
  171.  * as don't care; just as a regular escaped questionmark.
  172.  *
  173.  */
  174. char NO_WILD[1] = "";        /* Used as senitel value */
  175.  
  176. int getmagic(char *p, char **endpos, char *magic, char *mask)
  177. {
  178.   int count = 0;        /* Count of bytes */
  179.   int quote = 0;        /* Quoted? */
  180.   int ch;
  181.   int wildcards = 1;        /* Wildcards allowed by default */
  182.   enum { st_def, st_backsl, st_oct, st_hex, st_done } state = st_def;
  183.  
  184. #if DEBUG > 3
  185.   fprintf(stderr,"getmagic %s\n", p);
  186. #endif
  187.  
  188.   if ( mask == NO_WILD )    /* If wildcards forbidden */
  189.     {
  190.       mask = NULL;        /* Don't store a mask */
  191.       wildcards = 0;        /* Don't accept wildcards */
  192.     }
  193.  
  194.   while ( isspace(*p) ) p++;    /* Skip leading whitespace */
  195.   
  196.   while ( state != st_done )
  197.     {
  198.       switch ( state )
  199.     {
  200.     case st_def:
  201.       switch ( *p )
  202.         {
  203.         case '\n':        /* Unconditional whitespace */
  204.         case '\r':
  205.         case '\f':
  206.         case '\0':
  207.           if ( quote )
  208.         count = MAG_ERR;
  209.           state = st_done;
  210.           break;
  211.  
  212.         case '\\':        /* Backslash */
  213.           p++;
  214.           state = st_backsl;
  215.           break;
  216.  
  217.         case '\"':        /* Quote */
  218.           p++;
  219.           quote = !quote;
  220.           break;
  221.  
  222.         case '\b':        /* Whitespace */
  223.         case '\t':
  224.         case '\v':
  225.         case ' ':
  226.           if ( !quote )
  227.         {
  228.           state = st_done;
  229.           break;
  230.         }
  231.           /* else fall though */
  232.  
  233.         default:
  234.           if ( magic ) *(magic++) = *p;
  235.           if ( mask ) *(mask++) = (char)(-1);
  236.           p++; count++;
  237.           break;
  238.         }
  239.       break;
  240.       
  241.     case st_backsl:        /* After backslash */
  242.       ch = -1;
  243.       switch ( *p )
  244.         {
  245.         case 'a':
  246.           ch = 7;        /* Bell */
  247.           break;
  248.         case 'b':
  249.           ch = '\b';    /* Backspace */
  250.           break;
  251.         case 'e':
  252.           ch = 27;        /* Escape */
  253.           break;
  254.         case 'f':
  255.           ch = '\f';    /* Form feed */
  256.           break;
  257.         case 'n':
  258.           ch = '\n';    /* Newline */
  259.           break;
  260.         case 'r':
  261.           ch = '\r';    /* Return */
  262.           break;
  263.         case 't':
  264.           ch = '\t';    /* Tab */
  265.           break;
  266.         case 'v':
  267.           ch = '\v';    /* Vtab */
  268.           break;
  269.         case 'x':
  270.         case 'X':
  271.           state = st_hex;    /* Hex prefix */
  272.           ch = 0;
  273.           break;
  274.         case '0':
  275.         case '1':
  276.         case '2':
  277.         case '3':
  278.         case '4':
  279.         case '5':
  280.         case '6':
  281.         case '7':
  282.           state = st_oct;    /* Octal prefix */
  283.           ch = *p - '0';
  284.           break;
  285.         case '?':
  286.           if ( wildcards )
  287.         {
  288.           if ( magic ) *(magic++) = (char)0; /* Ignore byte */
  289.           if ( mask ) *(mask++) = (char)0;
  290.           count++;
  291.           state = st_def;
  292.           break;
  293.         }
  294.           /* else fall through */
  295.         default:
  296.           ch = *p;        /* Preserve character (e.g. " or \) */
  297.           break;
  298.         }
  299.       
  300.       p++;
  301.       
  302.       if ( state == st_backsl )
  303.         {
  304.           if ( magic ) *(magic++) = ch;
  305.           if ( mask ) *(mask++) = (char)(-1);
  306.           count++;
  307.           state = st_def;
  308.         }
  309.       break;
  310.  
  311.     case st_oct:
  312.       if ( *p >= '0' && *p <='7' )
  313.         {
  314.           ch <<= 3;
  315.           ch += *(p++) - '0';
  316.         }
  317.       else
  318.         {
  319.           if ( magic ) *(magic++) = ch;
  320.           if ( mask ) *(mask++) = (char)(-1);
  321.           count++;
  322.           state = st_def;    /* Do not advance p */
  323.         }
  324.       break;
  325.  
  326.     case st_hex:
  327.       if ( *p >= '0' && *p <= '9' )
  328.         {
  329.           ch <<= 4;
  330.           ch += *(p++) - '0';
  331.         }
  332.       else if ( *p >= 'A' && *p <= 'F' )
  333.         {
  334.           ch <<= 4;
  335.           ch += *(p++) - 'A' + 10;
  336.         }
  337.       else if ( *p >= 'a' && *p <= 'f' )
  338.         {
  339.           ch <<= 4;
  340.           ch += *(p++) - 'a' + 10;
  341.         }
  342.       else
  343.         {
  344.           if ( magic ) *(magic++) = ch;
  345.           if ( mask ) *(mask++) = (char)(-1);
  346.           count++;
  347.           state = st_def;    /* Do not advance p */
  348.         }
  349.       break;
  350.     }
  351.     }
  352.  
  353.   if (endpos) *endpos = p;
  354.   return count;
  355. }
  356.  
  357. /*
  358.  * enum actions getaction(char *pos, char **cmd)
  359.  *
  360.  * Reads the action proposed and returns:
  361.  *
  362.  * ACT_CAT       ... output file raw
  363.  * ACT_DROP      ... silently ignore
  364.  * ACT_REJECT    ... mail user and complain
  365.  * ACT_FILTER    ... run through once, then done
  366.  * ACT_PIPETHRU  ... run through command, then feed back through filter
  367.  * ACT_ADDCR     ... \n -> \r\n, \f -> \r\f
  368.  * ACT_PS        ... same as ADDCR, but add Ctrl-D at end
  369.  * ACT_FFILTER   ... same as FILTER, but use a temp file
  370.  * ACT_FPIPE     ... same as PIPETHRU, but use a temp file
  371.  *
  372.  * If the command takes an argument, point cmd to it if non-NULL
  373.  *
  374.  * IMPORTANT: The matching algorithm is a bit simplistic.  If any action
  375.  * is a proper prefix of any other action, the longer action must be first
  376.  * in the list.
  377.  */
  378.  
  379. enum actions getaction(char *pos, char **cmd)
  380. {
  381.   enum actions act;
  382.   static char *act_strs[] = { "cat", "ignore", "reject", "filter",
  383.                  "pipe", "text", "postscript",
  384.                  "ffilter", "fpipe", NULL };
  385.   char **act_str;
  386.   int i;
  387.  
  388. #if DEBUG > 3
  389.   fprintf(stderr,"getaction %s\n", pos);
  390. #endif
  391.   
  392.   while ( isspace(*pos) ) pos++; /* Ignore leading whitespace */
  393.   
  394.   if ( ! *pos )
  395.     return ACT_ERR;        /* Syntax error */
  396.     
  397.   for ( act = ACT_CAT, act_str = act_strs ; *act_str ; act++, act_str++ )
  398.     if ( strncmp(pos, *act_str, i = strlen(*act_str)) == 0 )
  399.       {
  400.     pos += i;
  401.     break;
  402.       }
  403.   
  404.   if ( ! *act_str )
  405.     {
  406. #if DEBUG > 3
  407.       fprintf(stderr,"No match\n");
  408. #endif
  409.       return ACT_ERR;        /* Unknown action */
  410.     }
  411.   
  412.   if ( *pos && !isspace(*pos) )
  413.     {
  414. #if DEBUG > 3
  415.       fprintf(stderr,"Garbage at end: %s\n", pos);
  416. #endif
  417.       return ACT_ERR;        /* Garbage after action name */
  418.     }
  419.  
  420.   if ( cmd )
  421.     {
  422.       while ( isspace(*pos) ) pos++; /* Skip leading whitespace again */
  423.       *cmd = pos;
  424.     }
  425.   
  426.   return act;
  427. }
  428.  
  429.